home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
misc
/
sci
/
ephem_src_4_28.lha
/
objx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-28
|
30KB
|
1,188 lines
/* functions to save the user-definable objects, referred to as "x" and "y".
* this way, once defined, the objects can be quieried for position just like
* the other bodies, with obj_cir().
*/
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#ifdef VMS
#include <stdlib.h>
#endif
#include "astro.h"
#include "circum.h"
#include "screen.h"
extern char *strcat(), *strcpy(), *strncpy(),
#ifdef AMIGA
*wgetenv();
#else
*getenv();
#endif
void obj_on(), obj_off(), obj_dfixed(), obj_delliptical(), obj_dhyperbolic(),
obj_dparabolic(), obj_cir(), crack_year();
static char *dbfile; /* !0 if set by -d option */
#ifdef AMIGA
static char dbfdef[] = "S:ephem.db"; /* default database file name */
#else
static char dbfdef[] = "ephem.db"; /* default database file name */
#endif
/* structures to describe objects of various types.
*/
#define MAXNM 16 /* longest allowed object name, inc \0 */
typedef struct {
double m_m1, m_m2; /* either g/k or H/G, depending on... */
int m_whichm; /* one of MAG_gk or MAG_HG */
} Mag;
typedef struct {
double f_ra; /* ra, rads, at given epoch */
double f_dec; /* dec, rads, at given epoch */
double f_mag; /* visual magnitude */
double f_siz; /* angular size, in arc seconds */
double f_epoch; /* the given epoch, as an mjd */
char f_name[MAXNM]; /* name */
} ObjF; /* fixed object */
typedef struct {
double e_inc; /* inclination, degrees */
double e_Om; /* longitude of ascending node, degrees */
double e_om; /* argument of perihelion, degress */
double e_a; /* mean distance, aka, semi-maj axis, in AU */
double e_n; /* daily motion, degrees/day */
double e_e; /* eccentricity */
double e_M; /* mean anomaly, ie, degrees from perihelion at... */
double e_cepoch; /* epoch date (M reference), as an mjd */
double e_epoch; /* equinox year (inc/Om/om reference), as an mjd */
Mag e_mag; /* magnitude */
double e_siz; /* angular size, in arc seconds at 1 AU */
char e_name[MAXNM]; /* name */
} ObjE; /* object in heliocentric elliptical orbit */
typedef struct {
double h_ep; /* epoch of perihelion, as an mjd */
double h_inc; /* inclination, degs */
double h_Om; /* longitude of ascending node, degs */
double h_om; /* argument of perihelion, degs. */
double h_e; /* eccentricity */
double h_qp; /* perihelion distance, AU */
double h_epoch; /* equinox year (inc/Om/om reference), as an mjd */
double h_g, h_k; /* magnitude model coefficients */
double h_siz; /* angular size, in arc seconds at 1 AU */
char h_name[MAXNM]; /* name */
} ObjH; /* object in heliocentric parabolic trajectory */
typedef struct {
double p_ep; /* epoch of perihelion, as an mjd */
double p_inc; /* inclination, degs */
double p_qp; /* perihelion distance, AU */
double p_om; /* argument of perihelion, degs. */
double p_Om; /* longitude of ascending node, degs */
double p_epoch; /* reference epoch, as an mjd */
double p_g, p_k; /* magnitude model coefficients */
double p_siz; /* angular size, in arc seconds at 1 AU */
char p_name[MAXNM]; /* name */
} ObjP; /* object in heliocentric parabolic trajectory */
typedef struct {
int o_type; /* current object type; see flags, below */
int o_on; /* !=0 while current object is active */
ObjF o_f; /* the fixed object */
ObjE o_e; /* the elliptical orbit object */
ObjH o_h; /* the hyperbolic orbit object */
ObjP o_p; /* the parabolic orbit object */
} Obj;
/* o_type */
#define FIXED 1
#define ELLIPTICAL 2
#define HYPERBOLIC 3
#define PARABOLIC 4
/* m_whichm */
#define MAG_HG 0 /* using 0 makes HG the initial default */
#define MAG_gk 1
static Obj objx;
static Obj objy;
#define DY 0 /* decimal year flag for set_year() */
#define YMD 1 /* year/mon/day flag for set_year() */
/* run when Objx or y is picked from menu.
* we tell which by the planet code.
* let op define object and turn it on and off.
*/
void obj_setup(p)
int p;
{
static char *pr[6] = { /* leave a slot for "On"/"Off" */
"Fixed", "Elliptical", "Hyperbolic", "Parabolic", "Lookup"
};
int f;
Obj *op;
op = (p == OBJX) ? &objx : &objy;
rechk:
/* map o_type to popup choice.
*/
switch (op->o_type) {
case FIXED: f = 0; break;
case ELLIPTICAL: f = 1; break;
case HYPERBOLIC: f = 2; break;
case PARABOLIC: f = 3; break;
default: f = 4; break;
}
ask:
pr[5] = op->o_on ? "On" : "Off";
switch (f = popup (pr, f, 6)) {
case 0: obj_dfixed(op, 0, (char**)0); goto ask;
case 1: obj_delliptical(op, 0, (char**)0); goto ask;
case 2: obj_dhyperbolic(op, 0, (char**)0); goto ask;
case 3: obj_dparabolic(op, 0, (char**)0); goto ask;
case 4: if (obj_filelookup(p, (char *)0) == 0) obj_on(p); goto rechk;
case 5: op->o_on ^= 1; break;
}
}
/* turn "on" or "off" but don't forget facts about object the object.
*/
void obj_on (p)
int p;
{
if (p == OBJX)
objx.o_on = 1;
else
objy.o_on = 1;
}
void obj_off (p)
int p;
{
if (p == OBJX)
objx.o_on = 0;
else
objy.o_on = 0;
}
/* return true if object is now on, else 0.
*/
obj_ison(p)
int p;
{
return ((p == OBJX) ? objx.o_on : objy.o_on);
}
/* set an alternate database file name.
* N.B. we assume the storage pointed to by name is permanent.
*/
void obj_setdbfilename (name)
char *name;
{
dbfile = name;
}
/* fill in info about object x or y.
* most arguments and conditions are the same as for plans().
* only difference is that mag is already apparent, not absolute magnitude.
* this is called by body_cir() for object x and y just like plans() is called
* for the planets.
*/
void obj_cir (jd, p, lpd0, psi0, rp0, rho0, lam, bet, siz, mag)
double jd; /* mjd now */
int p; /* OBJX or OBJY */
double *lpd0; /* heliocentric longitude, or NOHELIO */
double *psi0; /* heliocentric latitude, or 0 if *lpd0 set to NOHELIO */
double *rp0; /* distance from the sun, or 0 */
double *rho0; /* true distance from the Earth, or 0 */
double *lam; /* apparent geocentric ecliptic longitude */
double *bet; /* apparent geocentric ecliptic latitude */
double *siz; /* angular size of object, arc seconds */
double *mag; /* APPARENT magnitude */
{
Obj *op = (p == OBJX) ? &objx : &objy;
switch (op->o_type) {
case FIXED: {
double xr, xd;
xr = op->o_f.f_ra;
xd = op->o_f.f_dec;
if (op->o_f.f_epoch != jd)
precess (op->o_f.f_epoch, jd, &xr, &xd);
eq_ecl (jd, xr, xd, bet, lam);
*lpd0 = NOHELIO;
*psi0 = *rp0 = *rho0 = 0.0;
*mag = op->o_f.f_mag;
*siz = op->o_f.f_siz;
}
break;
case ELLIPTICAL: {
/* this is basically the same code as pelement() and plans()
* combined and simplified for the special case of osculating
* (unperturbed) elements.
* inputs have been changed to match the Astronomical Almanac.
* we have added reduction of elements using reduce_elements().
*/
double dt, lg, lsn, rsn;
double nu, ea;
double ma, rp, lo, slo, clo;
double inc, psi, spsi, cpsi;
double y, lpd, rpd, ll, rho, sll, cll;
double om; /* arg of perihelion */
double Om; /* long of ascending node. */
double e;
int pass;
dt = 0;
sunpos (jd, &lsn, &rsn);
lg = lsn + PI;
e = op->o_e.e_e;
for (pass = 0; pass < 2; pass++) {
reduce_elements (op->o_e.e_epoch, jd-dt, degrad(op->o_e.e_inc),
degrad (op->o_e.e_om), degrad (op->o_e.e_Om),
&inc, &om, &Om);
ma = degrad (op->o_e.e_M
+ (jd - op->o_e.e_cepoch - dt) * op->o_e.e_n);
anomaly (ma, e, &nu, &ea);
rp = op->o_e.e_a * (1-e*e) / (1+e*cos(nu));
lo = nu + om;
slo = sin(lo);
clo = cos(lo);
spsi = slo*sin(inc);
y = slo*cos(inc);
psi = asin(spsi);
lpd = atan(y/clo)+Om;
if (clo<0) lpd += PI;
range (&lpd, 2*PI);
cpsi = cos(psi);
rpd = rp*cpsi;
ll = lpd-lg;
rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
dt = rho*5.775518e-3; /* light travel time, in days */
if (pass == 0) {
*lpd0 = lpd;
*psi0 = psi;
*rp0 = rp;
*rho0 = rho;
}
}
sll = sin(ll);
cll = cos(ll);
if (rpd < rsn)
*lam = atan(-1*rpd*sll/(rsn-rpd*cll))+lg+PI;
else
*lam = atan(rsn*sll/(rpd-rsn*cll))+lpd;
range (lam, 2*PI);
*bet = atan(rpd*spsi*sin(*lam-lpd)/(cpsi*rsn*sll));
if (op->o_e.e_mag.m_whichm == MAG_HG) {
/* the H and G parameters from the Astro. Almanac.
*/
double psi_t, Psi_1, Psi_2, beta;
beta = acos((rp*rp + rho*rho - rsn*rsn)/ (2*rp*rho));
psi_t = exp(log(tan(beta/2.0))*0.63);
Psi_1 = exp(-3.33*psi_t);
psi_t = exp(log(tan(beta/2.0))*1.22);
Psi_2 = exp(-1.87*psi_t);
*mag = op->o_e.e_mag.m_m1 + 5.0*log10(rp*rho)
- 2.5*log10((1-op->o_e.e_mag.m_m2)*Psi_1
+ op->o_e.e_mag.m_m2*Psi_2);
} else {
/* the g/k model of comets */
*mag = op->o_e.e_mag.m_m1 + 5*log10(rho)
+ 2.5*op->o_e.e_mag.m_m2*log10(rp);
}
*siz = op->o_e.e_siz / rho;
}
break;
case HYPERBOLIC: {
double dt, lg, lsn, rsn;
double nu, ea;
double ma, rp, lo, slo, clo;
double inc, psi, spsi, cpsi;
double y, lpd, rpd, ll, rho, sll, cll;
double om; /* arg of perihelion */
double Om; /* long of ascending node. */
double e;
double a, n; /* semi-major axis, mean daily motion */
int pass;
dt = 0;
sunpos (jd, &lsn, &rsn);
lg = lsn + PI;
e = op->o_h.h_e;
a = op->o_h.h_qp/(e - 1.0);
n = .98563/sqrt(a*a*a);
for (pass = 0; pass < 2; pass++) {
reduce_elements (op->o_h.h_epoch, jd-dt, degrad(op->o_h.h_inc),
degrad (op->o_h.h_om), degrad (op->o_h.h_Om),
&inc, &om, &Om);
ma = degrad ((jd - op->o_h.h_ep - dt) * n);
anomaly (ma, e, &nu, &ea);
rp = a * (e*e-1.0) / (1.0+e*cos(nu));
lo = nu + om;
slo = sin(lo);
clo = cos(lo);
spsi = slo*sin(inc);
y = slo*cos(inc);
psi = asin(spsi);
lpd = atan(y/clo)+Om;
if (clo<0) lpd += PI;
range (&lpd, 2*PI);
cpsi = cos(psi);
rpd = rp*cpsi;
ll = lpd-lg;
rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
dt = rho*5.775518e-3; /* light travel time, in days */
if (pass == 0) {
*lpd0 = lpd;
*psi0 = psi;
*rp0 = rp;
*rho0 = rho;
}
}
sll = sin(ll);
cll = cos(ll);
if (rpd < rsn)
*lam = atan(-1*rpd*sll/(rsn-rpd*cll))+lg+PI;
else
*lam = atan(rsn*sll/(rpd-rsn*cll))+lpd;
range (lam, 2*PI);
*bet = atan(rpd*spsi*sin(*lam-lpd)/(cpsi*rsn*sll));
*mag = op->o_h.h_g + 5*log10(rho) + 2.5*op->o_h.h_k*log10(rp);
*siz = op->o_h.h_siz / rho;
}
break;
case PARABOLIC: {
double inc, om, Om;
double lpd, psi, rp, rho;
double dt;
int pass;
/* two passes to correct lam and bet for light travel time. */
dt = 0.0;
for (pass = 0; pass < 2; pass++) {
reduce_elements (op->o_p.p_epoch, jd-dt, degrad(op->o_p.p_inc),
degrad(op->o_p.p_om), degrad(op->o_p.p_Om), &inc, &om, &Om);
comet (jd-dt, op->o_p.p_ep, inc, om, op->o_p.p_qp, Om,
&lpd, &psi, &rp, &rho, lam, bet);
if (pass == 0) {
*lpd0 = lpd;
*psi0 = psi;
*rp0 = rp;
*rho0 = rho;
}
dt = rho*5.775518e-3; /* au to light-days */
}
*mag = op->o_p.p_g + 5*log10(rho) + 2.5*op->o_p.p_k*log10(rp);
*siz = op->o_p.p_siz / rho;
}
break;
default:
f_msg ((p == OBJX) ? "Obj X is not defined"
: "Obj Y is not defined");
break;
}
}
/* define obj based on the ephem.db line, s.
* p is one of OBJX or OBJY.
* format: name,type,[other fields, as per corresponding ObjX typedef]
* N.B. we replace all ',' within s with '\0' IN PLACE.
* return 0 if ok, else print reason why not with f_msg() and return -1.
*/
obj_define (p, s)
int p; /* OBJX or OBJY */
char *s;
{
#define MAXARGS 20
char *av[MAXARGS]; /* point to each field for easy reference */
char c;
int ac;
Obj *op = (p == OBJX) ? &objx : &objy;
/* parse into comma separated fields */
ac = 0;
av[0] = s;
do {
c = *s++;
if (c == ',' || c == '\0') {
s[-1] = '\0';
av[++ac] = s;
}
} while (c);
if (ac < 2) {
char buf[NC];
if (ac > 0)
(void) sprintf (buf, "No type for Object %s", av[0]);
else
(void) sprintf (buf, "No fields in %s", s);
f_msg (buf);
return (-1);
}
/* switch out on type of object - the second field */
switch (av[1][0]) {
case 'f':
if (ac != 6 && ac != 7) {
char buf[NC];
(void) sprintf(buf,
"Need ra,dec,mag,D[,siz] for fixed object %s", av[0]);
f_msg (buf);
return (-1);
}
obj_dfixed (op, ac, av);
break;
case 'e':
if (ac != 13 && ac != 14) {
char buf[NC];
(void) sprintf (buf,
"Need i,O,o,a,n,e,M,E,D,H/g,G/k[,siz] for elliptical object %s",
av[0]);
f_msg (buf);
return (-1);
}
obj_delliptical (op, ac, av);
break;
case 'h':
if (ac != 11 && ac != 12) {
char buf[NC];
(void) sprintf (buf,
"Need T,i,O,o,e,q,D,g,k[,siz] for hyperbolic object %s", av[0]);
f_msg (buf);
return (-1);
}
obj_dhyperbolic (op, ac, av);
break;
case 'p':
if (ac != 10 && ac != 11) {
char buf[NC];
(void) sprintf (buf,
"Need T,i,o,q,O,D,g,k[,siz] for parabolic object %s", av[0]);
f_msg (buf);
return (-1);
}
obj_dparabolic (op, ac, av);
break;
default: {
char buf[NC];
(void) sprintf (buf, "Unknown type for Object %s: %s",
av[0], av[1]);
f_msg (buf);
return (-1);
}
}
return (0);
}
/* if name, then look it up in the ephem database file and set p.
* else display a table of all objects and let op pick one.
* p is either OBJX or OBJY.
* if -d was used use it; else if EPHEMDB env set use it, else use default.
* return 0 if successfully set object p, else -1.
*/
obj_filelookup (p, name)
int p; /* OBJX or OBJY */
char *name;
{
/* redefine RCTN,NTR,NTC for column-major order if you prefer */
#define NLR (NR-1) /* number of rows of names.
* leave 1 for prompt
*/
#define LCW 9 /* screen columns per name */
#define NLC 9 /* total number of name columns */
#define NL (NLR*NLC) /* total number of names per screen */
#define RCTN(r,c) ((r)*NLC+(c)) /* row/col to index */
#define NTR(n) ((n)/NLC) /* index to row */
#define NTC(n) ((n)%NLC) /* index to col (0 based) */
/* N.B. all these are 0-based */
static char prompt[] =
"RETURN to select, p/n for previous/next page, q to quit";
FILE *fp;
char *fn;
int i, pgn; /* index on current screen, current page number */
int r, c;
char buf[160]; /* longer than any one database line */
char pb[NC]; /* prompt buffer */
int readahd; /* 1 if buffer set from previous loop */
int choice; /* index to selection; -1 until set */
int roaming; /* 1 while just roaming around screen */
int abandon; /* 1 if decide to not pick afterall */
/* open the database file */
if (dbfile)
fn = dbfile;
else {
#ifdef AMIGA
fn = wgetenv ("EPHEMDB");
#else
fn = getenv ("EPHEMDB");
#endif
if (!fn)
fn = dbfdef;
}
fp = fopen (fn, "r");
if (!fp) {
(void) sprintf (buf, "Can not open database file %s", fn);
f_msg(buf);
return(-1);
}
/* name is specified so just search for it without any op interaction */
if (name) {
int nl = strlen (name);
int ret = 0;
while (nxt_db(buf, sizeof(buf), fp) == 0 && strncmp(buf, name, nl))
continue;
if (feof(fp)) {
(void) sprintf (buf, "Object %s not found", name);
f_msg (buf);
ret = -1;
} else
(void) obj_define (p, buf);
(void) fclose (fp);
return (ret);
}
pgn = 0;
readahd = 0;
choice = -1;
abandon = 0;
/* continue until a choice is made or op abandons the attempt */
do {
/* put up next screen full of names.
* leave top row open for messages.
*/
c_erase();
for (i = 0; i < NL; )
if (readahd || nxt_db (buf, sizeof(buf), fp) == 0) {
char objname[LCW];
int ii;
for (ii = 0; ii < sizeof(objname)-1; ii++)
if ((objname[ii] = buf[ii]) == ',')
break;
objname[ii] = '\0';
if (i == NL-1)
objname[LCW-2] = '\0'; /* avoid scroll in low-r corner*/
f_string (NTR(i)+2, NTC(i)*LCW+1, objname);
i++;
readahd = 0;
} else
break;
/* read another to check for eof. if valid, set readahd for next
* time.
*/
if (nxt_db (buf, sizeof(buf), fp) == 0)
readahd = 1;
/* let op pick one. set cursor on first one.
* remember these r/c are 0-based, but c_pos() is 1-based
*/
(void) sprintf (pb, "Page %d%s. %s", pgn+1,
feof(fp) ? " (last)" : "", prompt);
f_prompt(pb);
r = c = 0;
roaming = 1;
do {
c_pos (r+2, c*LCW+1);
switch (read_char()) {
case 'h': /* left */
if (c == 0) c = NLC;
c -= 1;
if (RCTN(r,c) >= i)
c = NTC(i-1);
break;
case 'j': /* down */
if (++r == NLR) r = 0;
if (RCTN(r,c) >= i)
r = 0;
break;
case 'k': /* up */
if (r == 0) r = NLR;
r -= 1;
while (RCTN(r,c) >= i)
r -= 1;
break;
case 'l': /* right */
if (++c == NLC) c = 0;
if (RCTN(r,c) >= i)
c = 0;
break;
case REDRAW:
/* start over and skip over prior pages' entries */
rewind(fp);
for (i = 0; i < NL*pgn; i++)
(void) nxt_db (buf, sizeof(buf), fp);
readahd = 0;
roaming = 0;
break;
case 'p':
/* if not at first page, start over and skip back one
* pages' entries
*/
if (pgn > 0) {
rewind(fp);
pgn--;
for (i = 0; i < NL*pgn; i++)
(void) nxt_db (buf, sizeof(buf), fp);
readahd = 0;
roaming = 0;
}
break;
case 'n':
/* if not already at eof, we can go ahead another page */
if (!feof (fp)) {
pgn++;
roaming = 0;
}
break;
case END:
abandon = 1;
roaming = 0;
break;
case ' ': case '\r':
choice = NL*pgn + RCTN(r,c);
roaming = 0;
break;
}
} while (roaming);
} while (choice < 0 && !abandon);
if (choice >= 0) {
/* skip first choice entries; selection is the next one */
(void) rewind (fp);
for (i = 0; i < choice; i++)
(void) nxt_db (buf, sizeof(buf), fp);
(void) nxt_db (buf, sizeof(buf), fp);
(void) obj_define (p, buf);
}
(void) fclose (fp);
redraw_screen (2);
return (choice >= 0 ? 0 : -1);
}
/* read database file fp and put next valid entry into buf.
* return 0 if ok, else -1
*/
static
nxt_db (buf, blen, fp)
char buf[];
int blen;
FILE *fp;
{
char s;
while (1) {
if (fgets (buf, blen, fp) == 0)
return (-1);
s = buf[0];
if (isalpha(s))
return (0);
}
}
/* define a fixed object.
* args in av, in order, are name, type, ra, dec, magnitude, reference epoch
* and optional angular size.
* if av then it is a list of strings to use for each parameter, else must
* ask for each (but type). the av option is for cracking the ephem.db line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to FIXED.
* N.B. we don't error check av in any way, not even for length.
*/
static void
obj_dfixed (op, ac, av)
Obj *op;
int ac;
char *av[];
{
char buf[NC];
char *bp;
int sts;
op->o_type = FIXED;
if (set_name (av, op->o_f.f_name) < 0)
return;
if (av) {
bp = av[2];
sts = 1;
} else {
static char p[] = "RA (h:m:s): (";
f_prompt (p);
f_ra (R_PROMPT, C_PROMPT+sizeof(p)-1, op->o_f.f_ra);
#ifdef AMIGA
cwrite(") ");
#else
(void) printf (") ");
#endif
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0) {
int h, m, s;
f_dec_sexsign (radhr(op->o_f.f_ra), &h, &m, &s);
f_sscansex (bp, &h, &m, &s);
sex_dec (h, m, s, &op->o_f.f_ra);
op->o_f.f_ra = hrrad(op->o_f.f_ra);
}
if (av) {
bp = av[3];
sts = 1;
} else {
static char p[] = "Dec (d:m:s): (";
f_prompt (p);
f_gangle (R_PROMPT, C_PROMPT+sizeof(p)-1, op->o_f.f_dec);
#ifdef AMIGA
cwrite(") ");
#else
(void) printf (") ");
#endif
sts = read_line (buf, 9+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0) {
int dg, m, s;
f_dec_sexsign (raddeg(op->o_f.f_dec), &dg, &m, &s);
f_sscansex (bp, &dg, &m, &s);
sex_dec (dg, m, s, &op->o_f.f_dec);
op->o_f.f_dec = degrad(op->o_f.f_dec);
}
if (set_double (av, 4, "Magnitude: ", &op->o_f.f_mag) < 0)
return;
if (set_year (av, 5,"Reference epoch (UT Date, m/d.d/y or year.d): ",
DY, &op->o_f.f_epoch) < 0)
return;
if (ac == 7 || !av)
(void) set_double (av, 6, "Angular Size: ", &op->o_f.f_siz);
else
op->o_f.f_siz = 0.0;
}
/* define an object in an elliptical heliocentric orbit.
* 13 or 14 args in av, in order, are name, type, inclination, longitude of
* ascending node, argument of perihelion, mean distance (aka semi-major
* axis), daily motion, eccentricity, mean anomaly (ie, degrees from
* perihelion), epoch date (ie, time of the mean anomaly value), equinox year
* (ie, time of inc/lon/aop), two magnitude coefficients and optional size.
* the mag may be H/G or g/k model, set by leading g or H (use H/G if none).
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.db line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to ELLIPTICAL.
* N.B. we don't error check av in any way, not even for length.
*/
static void
obj_delliptical(op, ac, av)
Obj *op;
int ac;
char *av[];
{
op->o_type = ELLIPTICAL;
if (set_name (av, op->o_e.e_name) < 0)
return;
if (set_double (av, 2, "Inclination (degs):", &op->o_e.e_inc) < 0)
return;
if (set_double (av, 3, "Longitude of ascending node (degs):",
&op->o_e.e_Om) < 0)
return;
if (set_double (av, 4, "Argument of Perihelion (degs):",
&op->o_e.e_om) < 0)
return;
if (set_double (av, 5, "Mean distance (AU):", &op->o_e.e_a) < 0)
return;
if (set_double (av, 6, "Daily motion (degs/day):", &op->o_e.e_n) < 0)
return;
if (set_double (av, 7, "Eccentricity:", &op->o_e.e_e) < 0)
return;
if (set_double (av, 8, "Mean anomaly (degs):", &op->o_e.e_M) < 0)
return;
if (set_year (av, 9, "Epoch date (UT Date, m/d.d/y or year.d): ",
YMD, &op->o_e.e_cepoch) < 0)
return;
if (set_year (av, 10, "Equinox year (UT Date, m/d.d/y or year.d): ",
DY, &op->o_e.e_epoch) < 0)
return;
if (set_mag (av, 11, &op->o_e.e_mag) < 0)
return;
if (ac == 14 || !av)
(void) set_double (av, 13, "Angular Size @ 1 AU: ", &op->o_e.e_siz);
else
op->o_e.e_siz = 0.0;
}
/* define an object in heliocentric hyperbolic orbit.
* 11 or 12 args in av, in order, are name, type, epoch of perihelion,
* inclination, longitude of ascending node, argument of perihelion,
* eccentricity, perihelion distance, reference epoch, absolute magnitude
* and luminosity index, and optional size.
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.db line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to HYPERBOLIC.
* N.B. we don't error check av in any way, not even for length.
*/
static void
obj_dhyperbolic (op, ac, av)
Obj *op;
int ac;
char *av[];
{
op->o_type = HYPERBOLIC;
if (set_name (av, op->o_h.h_name) < 0)
return;
if (set_year(av,2,"Epoch of perihelion (UT Date, m/d.d/y or year.d): ",
YMD, &op->o_h.h_ep) < 0)
return;
if (set_double (av, 3, "Inclination (degs):", &op->o_h.h_inc) < 0)
return;
if (set_double (av, 4,
"Longitude of ascending node (degs):", &op->o_h.h_Om) < 0)
return;
if (set_double(av,5,"Argument of perihelion (degs):", &op->o_h.h_om) <0)
return;
if (set_double (av, 6, "Eccentricity:", &op->o_h.h_e) < 0)
return;
if (set_double (av, 7, "Perihelion distance (AU):", &op->o_h.h_qp) < 0)
return;
if (set_year (av, 8, "Reference epoch (UT Date, m/d.d/y or year.d): ",
DY, &op->o_h.h_epoch) < 0)
return;
if (set_double (av, 9, "g:", &op->o_h.h_g) < 0)
return;
if (set_double (av, 10, "k:", &op->o_h.h_k) < 0)
return;
if (ac == 12 || !av)
(void) set_double (av, 11, "Angular Size @ 1 AU: ", &op->o_h.h_siz);
else
op->o_h.h_siz = 0.0;
}
/* define an object in heliocentric parabolic orbit.
* 10 or 11 args in av, in order, are name, type, epoch of perihelion,
* inclination, argument of perihelion, perihelion distance, longitude of
* ascending node, reference epoch, absolute magnitude and luminosity index,
* and optional size.
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.db line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to PARABOLIC.
* N.B. we don't error check av in any way, not even for length.
*/
static void
obj_dparabolic(op, ac, av)
Obj *op;
int ac;
char *av[];
{
op->o_type = PARABOLIC;
if (set_name (av, op->o_p.p_name) < 0)
return;
if (set_year(av,2,"Epoch of perihelion (UT Date, m/d.d/y or year.d): ",
YMD, &op->o_p.p_ep) < 0)
return;
if (set_double (av, 3, "Inclination (degs):", &op->o_p.p_inc) < 0)
return;
if (set_double(av,4,"Argument of perihelion (degs):", &op->o_p.p_om) <0)
return;
if (set_double (av, 5, "Perihelion distance (AU):", &op->o_p.p_qp) < 0)
return;
if (set_double (av, 6,
"Longitude of ascending node (degs):", &op->o_p.p_Om) < 0)
return;
if (set_year (av, 7, "Reference epoch (UT Date, m/d.d/y or year.d): ",
DY, &op->o_p.p_epoch) < 0)
return;
if (set_double (av, 8, "g:", &op->o_p.p_g) < 0)
return;
if (set_double (av, 9, "k:", &op->o_p.p_k) < 0)
return;
if (ac == 11 || !av)
(void) set_double (av, 10, "Angular Size @ 1 AU: ", &op->o_p.p_siz);
else
op->o_p.p_siz = 0.0;
}
static
set_double (av, vn, pr, fp)
char *av[]; /* arg list */
int vn; /* which arg */
char *pr; /* prompt */
double *fp; /* ptr to double to be set */
{
int sts;
char buf[NC];
char *bp;
if (av) {
bp = av[vn];
sts = 1;
} else {
f_prompt (pr);
f_double (R_PROMPT, C_PROMPT+1+strlen(pr), "(%g) ", *fp);
sts = read_line (buf, 20);
if (sts < 0)
return (-1);
bp = buf;
}
if (sts > 0)
*fp = atof (bp);
return (0);
}
static
set_name (av, np)
char *av[]; /* arg list */
char *np; /* name to be set */
{
int sts;
char buf[NC];
char *bp;
if (av) {
bp = av[0];
sts = 1;
} else {
(void) sprintf (buf, "Name: (%s) ", np);
f_prompt (buf);
sts = read_line (buf, MAXNM-1);
if (sts < 0)
return (-1);
bp = buf;
}
if (sts > 0)
(void) strcpy (np, bp);
return (0);
}
static
set_year (av, vn, pr, type, yp)
char *av[]; /* arg list */
int vn; /* which arg */
char *pr; /* prompt */
int type; /* display type: YMD or DY */
double *yp; /* ptr to year to be set */
{
int sts;
char buf[NC];
char *bp;
#ifdef AMIGA
char bb[100];
#endif
if (av) {
bp = av[vn];
sts = 1;
} else {
f_prompt (pr);
if (type == DY) {
double y;
mjd_year (*yp, &y);
#ifdef AMIGA
sprintf(bb, "(%g) ", y);
cwrite(bb);
#else
(void) printf ("(%g) ", y);
#endif
} else {
int m, y;
double d;
mjd_cal (*yp, &m, &d, &y);
#ifdef AMIGA
sprintf(bb, "(%d/%g/%d) ", m, d, y);
cwrite(bb);
#else
(void) printf ("(%d/%g/%d) ", m, d, y);
#endif
}
sts = read_line (buf, 20);
if (sts < 0)
return (-1);
bp = buf;
}
if (sts > 0)
crack_year (bp, yp);
return (0);
}
/* given either a decimal year (xxxx. something) or a calendar (x/x/x)
* convert it to an mjd and store it at *p;
*/
static void
crack_year (bp, p)
char *bp;
double *p;
{
if (decimal_year(bp)) {
double y = atof (bp);
year_mjd (y, p);
} else {
int m, y;
double d;
mjd_cal (*p, &m, &d, &y); /* init with current */
f_sscandate (bp, &m, &d, &y);
cal_mjd (m, d, y, p);
}
}
/* read next two args from av and load the magnitude members m_m1 and m_m2.
* also set m_whichm to default if this is from the .db file, ie, if av!=0.
* #,# -> model is unchanged
* g#,[k]# -> g/k
* H#,[G]# -> H/G
*/
static
set_mag (av, vn, mp)
char *av[]; /* arg list */
int vn; /* which arg. we use av[vn] and av[vn+1] */
Mag *mp;
{
int sts;
char buf[NC];
char *bp;
if (av) {
mp->m_whichm = MAG_HG; /* always the default for the db file */
bp = av[vn];
sts = 1;
} else {
/* show both the value and the type of the first mag param,
* as well as a hint as to how to set the type if desired.
*/
(void) sprintf (buf, "%c: (%g) (g# H# or #) ",
mp->m_whichm == MAG_HG ? 'H' : 'g', mp->m_m1);
f_prompt (buf);
sts = read_line (buf, 9);
if (sts < 0)
return (-1);
bp = buf;
}
if (sts > 0) {
switch (bp[0]) {
case 'g':
mp->m_whichm = MAG_gk;
bp++;
break;
case 'H':
mp->m_whichm = MAG_HG;
bp++;
default:
/* leave type unchanged if no prefix */
break;
}
mp->m_m1 = atof (bp);
}
if (av) {
bp = av[vn+1];
sts = 1;
} else {
/* can't change the type in the second param */
(void) sprintf (buf, "%c: (%g) ",
mp->m_whichm == MAG_HG ? 'G' : 'k', mp->m_m2);
f_prompt (buf);
sts = read_line (buf, 9);
if (sts < 0)
return (-1);
bp = buf;
}
if (sts > 0) {
int ok = 0;
switch (bp[0]) {
case 'k':
if (mp->m_whichm == MAG_gk) {
bp++;
ok = 1;
}
break;
case 'G':
if (mp->m_whichm == MAG_HG) {
bp++;
ok = 1;
}
break;
default:
ok = 1;
break;
}
if (ok)
mp->m_m2 = atof (bp);
else {
f_msg ("Can't switch magnitude models at second parameter.");
return (-1);
}
}
return (0);
}